/*
 * Copyright 2014 by État de Genève (Switzerland)
 * All rights reserved.
 *
 * Author: ELCA Informatique SA
 */
define(function() {

    var _noPoursuiteRx = /^(\d{2})?\s?\d{2}\s?\d{6}\s?[a-zA-Z]$/;

    var _validCodeTypes = [ '00', '81', '82', '83', '84', '91', '92' ];
    var _controlSeq = 'ZYXWVUTSRPNMLKJHGFEDBCA';
    var _seqLength = _controlSeq.length;

    return {
        // checks if the given string is a valid no poursuite
        validate: validateNoPoursuite,
        // reformat a no poursuite (with space and capital letter)
        reformat: reformatString,
        // format string for technical use
        normalize: normalize,
        // transform a no poursuite string in an array of element for easy checking
        splitNoPoursuite: splitNoPoursuite
    };


    /**
     * Transform a valid noPoursuite into a string for exchange with Java API
     * string format is always: all numbers including leading 00, no space, uppercase.
     */
    function normalize(validNoPoursuite) {
        var exploded = splitNoPoursuite(validNoPoursuite);

        return exploded.join('').toUpperCase();
    }

    /**
     * Validates global shape and business rules for noPoursuite
     */
    function validateNoPoursuite(noPoursuite) {
        if(!noPoursuite) {
            return false;
        }

        // should be a string, otherwise don't know what to do...
        if(typeof noPoursuite === 'string') {
            // check global shape of number (accepts lowercase and no space)
            if(!noPoursuite.match(_noPoursuiteRx)) {
                return false;
            }

            // extract various parts
            var exploded = splitNoPoursuite(noPoursuite);
            // length should match (splitNoPoursuite adds leading 00 even if not present)
            if(exploded.length !== 4) {
                return false;
            }

            // first part has to match the type!
            if(_.indexOf(_validCodeTypes, exploded[0]) < 0) {
                return false;
            }

            // build number from strings, and compute checksum
            var number = parseInt(exploded[0] + exploded[1] + exploded[2] + '', 10);
            var x = number % _seqLength;

            // check checksum
            return _controlSeq[x] === exploded[3];
        }

        return false;
    }

    /**
     * reconstruct string to a beautiful clean string with spaces and upper case
     * Leading 00 is removed if exists
     */
    function reformatString(validInput) {
        var exploded = splitNoPoursuite(validInput);
        if(exploded.length === 4 && exploded[0] === '00') {
            exploded.shift();
        }
        return exploded.join(' ');
    }

    /**
     * extracts 4 parts (as strings) of a no poursuite string. If fails, returns an empty array
     */
    function splitNoPoursuite(validStr) {
        if(!validStr || typeof validStr !== 'string') {
            return [];
        }
        validStr = validStr.replace(/\s/g, '');

        if(validStr.length !== 11 && validStr.length !== 9) {
            return [];
        }
        var codeType = '00';
        if(validStr.length === 11) {
            codeType = validStr.slice(0, 2);
            validStr = validStr.slice(2);
        }
        return [codeType, validStr.slice(0, 2), validStr.slice(2, 8), validStr.slice(8).toUpperCase()];
    }

});
